#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>

#include "pear_block.h"
#include "log/pear_log.h"
#include "pear_block_ctx.h"
#include "utils/pear_dump.h"
#include "crypto/pear_key.h"


pr_block_ctx_t *pr_new_block_ctx()
{
    pr_block_ctx_t *bct = NULL;

    bct = (pr_block_ctx_t *) malloc(sizeof(*bct));
    if (bct == NULL)
    {
        return NULL;
    }

    memset(bct, 0x00, sizeof(*bct));

    return bct;
}


pr_block_t *pr_new_block(pr_block_ctx_t *blk_ctx)
{
    GList          *temp      = NULL;
    pr_block_t     *blk       = NULL;
    pr_block_t     *blk_prev  = NULL;
    pr_list_data_t *list_data = NULL;
    pr_list_data_t *last_data = NULL;

    pr_block_header_t *header = NULL;

    struct timeval ts;
    unsigned char hash[32] = {0x00};

    list_data = (pr_list_data_t *) malloc(sizeof(*list_data));
    if (list_data == NULL)
    {
        PEAR_LOG("malloc blk error\n");
        return NULL;
    }

    memset(list_data, 0x00, sizeof(*list_data));

    /*
     * Init This Block Info
     */
    blk    = &list_data->blk;
    header = &blk->header;

    if (blk_ctx->blk_list == NULL)
    {
        header->nonce = 0;
    }
    else
    {
        /* Make nonce For Hash */
        /*
        srand((int)time(0));
        header->nonce = rand();
        */
        header->nonce = 0;

        temp      = g_list_last(blk_ctx->blk_list);
        last_data = (pr_list_data_t *)temp->data; 
        blk_prev  = &last_data->blk;

        /* TODO: sum blk_prev hash */

        memcpy(header->prev_block, last_data->blk_hash, sizeof(last_data->blk_hash));
    }

    gettimeofday(&ts, NULL);
    //blk->header.timestamp  = ts.tv_sec;
    PEAR_LOG("timestamp: %d\n", blk->header.timestamp);

    /* 0 for temp */
    blk->header.total_gas  = 0;
    blk->header.tx_counter = 0;

    blk_ctx->height++;
    blk->header.number = blk_ctx->height;

    PEAR_LOG("height: %ld\n", blk_ctx->height);

    pr_hash256((char *)blk, sizeof(*blk), list_data->blk_hash);

    char test_buf[1024];
    PEAR_LOG("=========hash: %s==========\n", pr_hex_encode(test_buf, list_data->blk_hash, sizeof(list_data->blk_hash)));

    /*
    memcpy(blk->merkle_root);
    memcpy(blk->coinbase);
    */

    if ((blk_ctx->blk_list = g_list_append(blk_ctx->blk_list, list_data)) == NULL)
    {
        PEAR_LOG("g_list_append list_data error\n");
        free(blk);
        return NULL;
    }

    return blk;
}

char *pr_block_hash(pr_block_ctx_t *blk_ctx, pr_block_t *blk, unsigned char *hash, int hash_len)
{
    if (hash_len <  32)
    {
        PEAR_LOG("hash_len error\n");
        return NULL;
    }

    pr_hash256((char *)blk, sizeof(*blk), hash);

    return NULL;
}

long int pr_query_height(pr_block_ctx_t *blk_ctx)
{
    return blk_ctx->height;
}


unsigned char *pr_last_block_hash(pr_block_ctx_t *blk_ctx)
{
    GList          *temp      = NULL;
    pr_block_t     *blk       = NULL;
    pr_list_data_t *last_data = NULL;

    temp      = g_list_last(blk_ctx->blk_list);
    last_data = (pr_list_data_t *)temp->data;

    return last_data->blk_hash;
}





